//package com.fishbone.sso.interceptor;
//
//import com.fishbone.common.utils.Func;
//import com.fishbone.jwt.JwtTokenGenerator;
//import com.fishbone.jwt.JwtTokenPair;
//import com.fishbone.jwt.JwtTokenStorage;
//import com.fishbone.jwt.constants.AuthConstants;
//import com.fishbone.secure.handler.FishBoneAuthenticationEntryPoint;
//import com.nimbusds.jwt.JWTClaimsSet;
//import lombok.SneakyThrows;
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.http.HttpHeaders;
//import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
//import org.springframework.security.authentication.BadCredentialsException;
//import org.springframework.security.authentication.CredentialsExpiredException;
//import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
//import org.springframework.security.core.AuthenticationException;
//import org.springframework.security.core.GrantedAuthority;
//import org.springframework.security.core.authority.AuthorityUtils;
//import org.springframework.security.core.context.SecurityContextHolder;
//import org.springframework.security.core.userdetails.User;
//import org.springframework.security.web.AuthenticationEntryPoint;
//import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
//import org.springframework.util.StringUtils;
//import org.springframework.web.filter.OncePerRequestFilter;
//
//import javax.servlet.FilterChain;
//import javax.servlet.ServletException;
//import javax.servlet.http.HttpServletRequest;
//import javax.servlet.http.HttpServletResponse;
//import java.io.IOException;
//import java.util.Arrays;
//import java.util.List;
//import java.util.Objects;
//
///**
// * @ClassName FishBoneTokenFilter
// * @Author huyaxi
// * @DATE 2020/4/1 16:58
// */
//@Slf4j
//public class FishBoneUserTokenFilter extends OncePerRequestFilter {
//    private static final String AUTHENTICATION_PREFIX = "Bearer ";
//
//    private AuthenticationEntryPoint authenticationEntryPoint = new FishBoneAuthenticationEntryPoint();
//
//    private JwtTokenStorage jwtTokenStorage;
//
//    private JwtTokenGenerator jwtTokenGenerator;
//
//    public FishBoneUserTokenFilter(JwtTokenGenerator jwtTokenGenerator,JwtTokenStorage jwtTokenStorage) {
//        this.jwtTokenGenerator = jwtTokenGenerator;
//        this.jwtTokenStorage = jwtTokenStorage;
//    }
//
//
//    @Override
//    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
//        log.info("开始校验用户登录Token......");
//        if (SecurityContextHolder.getContext().getAuthentication() != null) {
//            filterChain.doFilter(request, response);
//            return;
//        }
//        String header = request.getHeader(HttpHeaders.AUTHORIZATION);
//        if (StringUtils.hasText(header) && header.startsWith(AUTHENTICATION_PREFIX)) {
//            String jwtToken = header.replace(AUTHENTICATION_PREFIX, "");
//            if (StringUtils.hasText(jwtToken)) {
//                try {
//                    authenticationTokenHandle(jwtToken, request);
//                } catch (AuthenticationException e) {
//                    authenticationEntryPoint.commence(request, response, e);
//                }
//            } else {
//                // 带安全头 没有带token
//                authenticationEntryPoint.commence(request, response, new AuthenticationCredentialsNotFoundException("token is not found"));
//            }
//        }else {
//            authenticationEntryPoint.commence(request, response, new AuthenticationCredentialsNotFoundException("token is not found"));
//        }
//        filterChain.doFilter(request, response);
//    }
//
//
//    /**
//     * 具体的认证方法  匿名访问不要携带token
//     * 有些逻辑自己补充 这里只做基本功能的实现
//     *
//     * @param jwtToken jwt token
//     * @param request  request
//     */
//    @SneakyThrows
//    private void authenticationTokenHandle(String jwtToken, HttpServletRequest request) throws AuthenticationException {
//
//        // 根据我的实现 有效token才会被解析出来
//        JWTClaimsSet claimsSet = jwtTokenGenerator.decodeAndVerify(jwtToken);
//        if (Objects.nonNull(claimsSet)) {
//            // 从缓存获取 token
//            String tokenKey = jwtTokenGenerator.generateAud(claimsSet.getStringClaim(AuthConstants.ACCOUNT),
//                    claimsSet.getLongClaim(AuthConstants.UID),claimsSet.getLongClaim(AuthConstants.TENANT_ID));
//            JwtTokenPair jwtTokenPair = jwtTokenStorage.get(tokenKey);
//            if (Objects.isNull(jwtTokenPair)) {
//                if (log.isDebugEnabled()) {
//                    log.debug("token : {}  is  not in cache", jwtToken);
//                }
//                // 缓存中不存在就算 失败了
//                throw new CredentialsExpiredException("token is not in cache");
//            }
//            String accessToken = jwtTokenPair.getAccessToken();
//            if (jwtToken.equals(accessToken)) {
//                // 解析 权限集合  这里
//                List<String> roleIds = Arrays.asList(Func.splitTrim(claimsSet.getStringClaim(AuthConstants.ROLE_IDS), ","));
//                List<GrantedAuthority> authorities = AuthorityUtils.commaSeparatedStringToAuthorityList(Func.join(roleIds));
//                User user = new User(claimsSet.getStringClaim(AuthConstants.ACCOUNT), "[PROTECTED]", authorities);
//                // 构建用户认证token
//                UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(user, null, authorities);
//                usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
//                // 放入安全上下文中
//                SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
//            } else {
//                // token 不匹配
//                if (log.isDebugEnabled()){
//                    log.debug("token : {}  is  not in matched", jwtToken);
//                }
//                throw new BadCredentialsException("token is not matched");
//            }
//        } else {
//            if (log.isDebugEnabled()) {
//                log.debug("token : {}  is  invalid", jwtToken);
//            }
//            throw new BadCredentialsException("token is invalid");
//        }
//    }
//}
